package com.hzxgs.tracelogstarter.trace;

import com.hzxgs.tracelogstarter.properties.TraceProperties;
import com.hzxgs.tracelogstarter.util.TraceUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@ChannelHandler.Sharable
@ConditionalOnClass(value = { SimpleChannelInboundHandler.class })
@Scope("prototype")
@Slf4j
public class NettyTraceServerHandler extends SimpleChannelInboundHandler {

    @Resource
    private TraceProperties traceProperties;

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        if (traceProperties.getEnable()) {
            log.info("netty连接断开");
            TraceUtils.removeTrace();
        }
        ctx.pipeline().remove(this);
        ctx.deregister();
        ctx.close();
        ctx.fireChannelInactive();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
        if (traceProperties.getEnable()) {
            TraceUtils.addTrace();
            log.info("netty接受到请求，增加traceId：{}，spanId：{}", TraceUtils.getTraceId(), TraceUtils.getSpanId());
        }
        // 不设置时，在返回时会报错
        ByteBuf buf = (ByteBuf) msg;
        buf.retain();
        // 调用下一个handler
        channelHandlerContext.fireChannelRead(msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        if (traceProperties.getEnable()) {
            log.error("netty发生异常，清除traceId");
            TraceUtils.removeTrace();
        }

        cause.printStackTrace();
        ctx.pipeline().remove(this);
        ctx.deregister();
        ctx.close();
        ctx.fireExceptionCaught(cause);
    }
}
